package lhglogger

import (
	"fmt"
	"os"
	"time"
)

//往文件中写日志相关代码

// 文件日志结构体
type FileLogger struct {
	Level       LogLevel
	filePath    string //日志文件保存的路径
	fileName    string //日志文件保存的文件名
	maxFileSize int64  //日志最大大小
}

// NewFileLogger构造函数
func NewFileLogger(LevelStr, fp, fn string, maxSize int64) *FileLogger {
	//将字符串日志级别转换为常量
	level := parseLevelStr(LevelStr)
	return &FileLogger{
		Level:       level,
		filePath:    fp,
		fileName:    fn,
		maxFileSize: maxSize,
	}
}

//记录各种日志级别的日志

// 验证level级别的日志是否记录 true:要记录 false:不记录
func (l *FileLogger) enable(level LogLevel) bool {
	return l.Level <= level
}

//封装直接输入日志的方法
func (l *FileLogger) printLog(level LogLevel, format string, a ...interface{}) {

	if l.enable(level) {
		msg := fmt.Sprintf(format, a...)
		now := time.Now()
		//注意：这里为啥传3，是因为最终在使用时 我要记录的是 调用当前Debug()的那行代码的位置
		funcName, fileName, lineNo := getInfo(3)
		levelstr := parseLevelToStr(level)
		//标准化的日志记录
		logmsg := fmt.Sprintf("[%s] [%v] %s [%s %d行 %s ]\n", now.Format("2006-01-02 15:04:05"), levelstr, msg, fileName, lineNo, funcName)
		//切割日志文件：根据配置 限制的日志大小进行切割

		//拼接文件名
		fullFileName := l.filePath + l.fileName + ".log"

		if l.checkSplitFile(fullFileName) == true {
			//要做切割操作
			//step1:对当前这个日志文件进行备份操作
			//拼接一个备份文件
			filenow := time.Now()
			bakfullFileName := l.filePath + l.fileName + "bak" + filenow.Format("20060102150405") + ".log"
			err := os.Rename(fullFileName, bakfullFileName)
			if err != nil {
				//如果备份出错
				fmt.Println(err)
			}
			//step2:打开新的日志文件，记日志
			fileObj, err := os.OpenFile(fullFileName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
			if err != nil {
				panic(err)
			}
			defer fileObj.Close()
			fileObj.WriteString(logmsg)

		} else {
			//不用切割，继续往当前这个文件里面写
			//向文件中记录日志
			fileObj, err := os.OpenFile(fullFileName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
			if err != nil {
				panic(err)
			}
			defer fileObj.Close()
			fileObj.WriteString(logmsg)
		}
	}
}

// 分析 l 中可以获取到 配置的限制大小数据，传一个文件名（拼接好的文件名{fullFileName,带路径的}）
// true:要做切割，false：不切割
func (l *FileLogger) checkSplitFile(fullFileName string) bool {
	fileObj, err := os.Open(fullFileName)

	if err != nil {
		return false
	}
	defer fileObj.Close()

	//获取文件信息
	fileInfo, err1 := fileObj.Stat()

	if err1 != nil {
		return false
	}
	//获取文件大小
	size := fileInfo.Size()
	if size >= l.maxFileSize {
		return true
	} else {
		return false
	}

}

// Debug级别 msg 可以支持格式化
func (l *FileLogger) Debug(format string, a ...interface{}) {
	l.printLog(DEBUG, format, a...)
}

// Info级别
func (l *FileLogger) Info(format string, a ...interface{}) {
	l.printLog(INFO, format, a...)
}

// Werning级别
func (l *FileLogger) Warning(format string, a ...interface{}) {
	l.printLog(WARNING, format, a...)
}

// Error级别
func (l *FileLogger) Error(format string, a ...interface{}) {

	l.printLog(ERROR, format, a...)
}

// Fatal级别
func (l *FileLogger) Fatal(format string, a ...interface{}) {
	l.printLog(FATAL, format, a...)
}
